package zzs.generalframework.util.core.file;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.ListIterator;

import zzs.generalframework.util.core.string.StringUtils;

/**
 * @title
 * @description
 * @project zzs-util
 * @package zzs.generalframework.util.core.file
 * @author zzs
 * @date 2018年1月30日
 * @version 1.0
 */
public class FileUtils
{

	private static final String character_encode_UTF8 = "UTF-8";

	/**
	 * 移动文件到另一个目录下
	 * 
	 * @param source
	 * @param destination
	 * @return
	 */
	public static boolean move(File source, File destination)
	{
		if (!source.exists())
		{
			return false;
		}

		destination.delete();

		return source.renameTo(destination);
	}

	/**
	 * 创建文件目录
	 * 
	 * @param directoryPath
	 * @return
	 */
	public static boolean createDirectory(String directoryPath)
	{
		if (null == directoryPath || "".equals(directoryPath.trim()))
		{
			return false;
		}

		File directory = new File(directoryPath);
		if (!directory.exists())
		{
			try
			{
				directory.mkdirs();
			}
			catch (Exception e)
			{
				e.printStackTrace();
				return false;
			}
		}
		return true;
	}

	/**
	 * 创建文件到目录中
	 * 
	 * @param directoryPath
	 * @param fileName
	 * @return
	 */
	public static boolean createFileToDirectory(String directoryPath, String fileName)
	{
		if (null == directoryPath || "".equals(directoryPath.trim()) || null == fileName || "".equals(fileName.trim()))
		{
			return false;
		}

		File directory = new File(directoryPath.trim());
		if (!directory.exists())
		{
			try
			{
				directory.mkdirs();
			}
			catch (Exception e)
			{
				e.printStackTrace();
				return false;
			}
		}

		String localFilePath = directoryPath.trim().concat(System.getProperty("file.separator")).concat(fileName.trim());
		File file = new File(localFilePath);

		if (!file.exists())
		{
			try
			{
				file.createNewFile();
			}
			catch (IOException e)
			{
				e.printStackTrace();
				return false;
			}
		}
		return true;
	}

	public static String readFile(String filePathName)
	{
		String returnString = "";
		if (StringUtils.isNotNullAndBlank(filePathName))
		{
			returnString = readFile(new File(filePathName));
		}
		return returnString;
	}

	/**
	 * 读文件
	 * 
	 * @param file
	 * @return
	 */
	public static String readFile(File file)
	{
		return readFile(file, character_encode_UTF8);
	}

	/**
	 * 读文件
	 * 
	 * @param file
	 * @param characterSet
	 * @return
	 */
	public static String readFile(File file, String characterSet)
	{
		StringBuffer stringBuffer = null;
		BufferedReader bufferedReader = null;
		if (null != file)
		{
			try
			{
				String path = file.getPath();
				stringBuffer = new StringBuffer();
				bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(path), characterSet));

				String line = null;

				while ((line = bufferedReader.readLine()) != null)
				{
					stringBuffer.append(line);
					stringBuffer.append('\n');
				}
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
			finally
			{
				try
				{
					if (null != bufferedReader)
					{
						bufferedReader.close();
					}
				}
				catch (IOException e)
				{
					e.printStackTrace();
				}
			}
		}

		return stringBuffer.toString();
	}

	/**
	 * 写文件
	 * 
	 * @param strContent
	 *            文件内容
	 * @param filename
	 */
	public static void write(String strContent, String filename)
	{
		FileOutputStream fileOutputStream = null;

		if (null != filename && !"".equals(filename))
		{
			try
			{
				StringBuffer sb = new StringBuffer(strContent);

				File file = new File(filename);

				if (!file.exists())
				{
					try
					{
						file.createNewFile();
					}
					catch (IOException e)
					{
						e.printStackTrace();
					}
				}

				fileOutputStream = new FileOutputStream(file, true);
				fileOutputStream.write(sb.toString().getBytes(character_encode_UTF8));
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
			finally
			{
				if (null != fileOutputStream)
				{
					try
					{
						fileOutputStream.close();
					}
					catch (IOException e)
					{
						e.printStackTrace();
					}
				}
			}
		}
	}

	/**
	 * 拷贝文件
	 * 
	 * @param source
	 * @param destination
	 * @param lazy
	 */
	public static void copyFile(File source, File destination, boolean lazy)
	{
		if (!source.exists())
		{
			return;
		}

		if (lazy)
		{
			String oldContent = null;

			try
			{
				oldContent = readFile(source);
			}
			catch (Exception e)
			{
				return;
			}

			String newContent = null;

			try
			{
				newContent = readFile(destination);
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}

			if (oldContent == null || !oldContent.equals(newContent))
			{
				copyFile(source, destination, false);
			}
		}
		else
		{
			if ((destination.getParentFile() != null) && (!destination.getParentFile().exists()))
			{

				destination.getParentFile().mkdirs();
			}

			FileInputStream fileInputStream = null;
			FileOutputStream fileOutputStream = null;

			FileChannel srcChannel = null;
			FileChannel dstChannel = null;
			try
			{
				fileInputStream = new FileInputStream(source);
				fileOutputStream = new FileOutputStream(destination);

				srcChannel = fileInputStream.getChannel();
				dstChannel = fileOutputStream.getChannel();

				dstChannel.transferFrom(srcChannel, 0, srcChannel.size());

			}
			catch (IOException ioe)
			{
				ioe.printStackTrace();
			}
			finally
			{
				try
				{
					if (dstChannel != null)
					{
						dstChannel.close();
					}
					if (fileOutputStream != null)
					{
						fileInputStream.close();
					}
					if (srcChannel != null)
					{
						srcChannel.close();
					}
					if (fileInputStream != null)
					{
						fileInputStream.close();
					}
				}
				catch (IOException e)
				{
					e.printStackTrace();
				}

			}
		}
	}

	/**
	 * 删除文件
	 * 
	 * @param localFilePath
	 */
	public static void deleteFile(String localFilePath)
	{
		if (null == localFilePath || "".equals(localFilePath))
		{
			return;
		}
		File file = new File(localFilePath);
		try
		{
			if (file.exists())
			{
				file.delete();
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * 判断文件是否存在
	 * 
	 * @param localFilePath
	 * @return
	 */
	public static boolean isExists(String localFilePath)
	{
		boolean isExists = false;
		if (null == localFilePath || "".equals(localFilePath.trim()))
		{
			return isExists;
		}
		File file = new File(localFilePath.trim());
		try
		{
			if (file.exists())
			{
				isExists = true;
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}

		return isExists;
	}

	/**
	 * 删除目录下文件
	 * 
	 * @param path
	 */
	public static void deleteDirFile(String path)
	{
		if (null == path || "".equals(path.trim()))
		{
			return;
		}

		File file = new File(path);

		String[] name = file.list();

		if (null != name && name.length > 0)
		{
			for (int i = 0; i < name.length; i++)
			{
				String delPath = path.concat(System.getProperty("file.separator").concat(name[i]));
				deleteFile(delPath);
			}
		}
	}

	/**
	 * 获取目录下文件的路径列表
	 * 
	 * @param dirPath
	 * @return
	 */
	public static List<String> getFilePath(String dirPath)
	{
		List<String> filePathlist = new ArrayList<String>();

		if (null == dirPath || "".equals(dirPath))
		{
			return filePathlist;
		}

		// 在工作文件夹中读取文件
		File file = new File(dirPath);

		// 文件名称数组
		String[] fileName = file.list();

		// 当有文件时
		if (fileName != null && fileName.length > 0)
		{
			for (int i = 0; i < fileName.length; i++)
			{
				// 文件路径
				String path = "";
				path = path.concat(dirPath).concat(System.getProperty("file.separator").concat(fileName[i].trim()));
				filePathlist.add(path);
			}
		}
		return filePathlist;
	}

	/**
	 * 把一个目录下的所有文件拷贝到另一个目录下
	 * 
	 * @param source
	 * @param destinate
	 * @return
	 */
	public static boolean copyFiles(String source, String destinate)
	{
		// 空参数判断
		if (null == source || source.trim().equals("") || null == destinate || destinate.trim().equals(""))
		{
			return false;
		}

		if (!FileUtils.isExists(source) || !FileUtils.isExists(destinate))
		{
			return false;
		}

		File SourceFile = new File(source);
		File desFile = new File(destinate);

		// 如果不是目录，返回
		if (!SourceFile.isDirectory() || !desFile.isDirectory())
		{
			return false;
		}

		List<String> filePaths = FileUtils.getFilePath(source);
		ListIterator<String> it = filePaths.listIterator();

		// 逐个拷贝
		while (it.hasNext())
		{
			synchronized (filePaths)
			{
				String filename = it.next().toString();
				if (!filename.trim().equals(""))
				{
					File aFile = new File(filename);
					String souname = aFile.getName();
					String dest = destinate.concat(System.getProperty("file.separator")).concat(souname);
					FileUtils.copyFile(aFile, new File(dest), true);
				}
			}
		}

		return true;
	}

	/**
	 * 把一个目录下的指定文件拷贝到另一个目录下 source copy源文件路径+名称 destinate copy 文件路径 filename
	 * copy目标文件名称
	 * 
	 * @param source
	 * @param folderpath
	 * @param filename
	 * @return
	 * @throws IOException
	 */
	public static boolean copyFile(String source, String folderpath, String filename) throws IOException
	{
		BufferedInputStream inBuff = null;
		BufferedOutputStream outBuff = null;

		if (null == source || source.trim().equals("") || null == filename || filename.trim().equals(""))
		{
			return false;
		}

		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		String target = folderpath + sdf.format(new Date());
		// 创建文件夹
		FileUtils.createDirectory(target);
		File sourceFile = new File(source);
		File targetFile = new File(target + File.separator + filename);
		try
		{
			// 新建文件输入流并对它进行缓冲
			inBuff = new BufferedInputStream(new FileInputStream(sourceFile));

			// 新建文件输出流并对它进行缓冲
			outBuff = new BufferedOutputStream(new FileOutputStream(targetFile));

			// 缓冲数组
			byte[] b = new byte[1024 * 5];
			int len;
			while ((len = inBuff.read(b)) != -1)
			{
				outBuff.write(b, 0, len);
			}
			// 刷新此缓冲的输出流
			outBuff.flush();
		}
		finally
		{
			// 关闭流
			if (inBuff != null)
			{
				inBuff.close();
			}

			if (outBuff != null)
			{
				outBuff.close();
			}

		}
		return true;
	}

	/**
	 * 删除子文件
	 * 
	 * @param dir
	 */
	public static void deleteSubFiles(File dir)
	{

		File[] files = dir.listFiles();
		if (null == files)
		{
			return;
		}

		for (int i = 0; i < files.length; i++)
		{
			if (files[i].isDirectory())
			{
				deleteSubFiles(files[i]);
			}
			else
			{
				try
				{
					(files[i]).delete();
				}
				catch (Exception e)
				{
					return;
				}
			}
		}
	}

	/**
	 * 得到指定文件夹下的指定文件的路径
	 * 
	 * @param dir
	 * @param filename
	 * @param filePath
	 * @return
	 */
	public static String getFilePath(File dir, String filename, String filePath)
	{
		File[] files = dir.listFiles();
		if (null == files)
		{
			return filePath;
		}

		for (int i = 0; i < files.length; i++)
		{
			if (files[i].isDirectory())
			{
				getFilePath(files[i], filename, filePath);
			}
			else
			{
				if (files[i].getName().equals(filename))
				{
					filePath = files[i].getAbsolutePath();
				}
			}
		}
		return filePath;
	}

	/**
	 * 删除文件，目录
	 * 
	 * @param indexCopy
	 */
	public static void deleteDiretory(File indexCopy)
	{
		File[] files = indexCopy.listFiles();
		for (int i = 0; i > files.length; i++)
		{
			if (files[i].isDirectory())
			{
				deleteDiretory(files[i]);
			}
			else
			{
				files[i].delete();
			}
		}
	}

	/**
	 * 将一个字符串按照某分隔符隔开，再按照另一个分隔符重新组合
	 * 
	 * @param fileName
	 * @param regex
	 * @param seperator
	 * @return
	 */
	public static String convertPath(String fileName, String regex, String seperator)
	{

		String[] fileParts = fileName.split(regex);
		String targetPath = "";

		for (int i = 0; i < fileParts.length; i++)
		{
			targetPath = targetPath.concat(fileParts[i]);
			if (i < fileParts.length - 1)
			{
				targetPath = targetPath.concat(seperator);
			}
		}
		return targetPath;

	}

	/**
	 * 删除已经存在的文件夹及文件
	 * 
	 * @param folderPath
	 */
	public static void delFolder(String folderPath)
	{
		try
		{
			delAllFile(folderPath); // 删除完里面所有内容
			String filePath = folderPath;
			filePath = filePath.toString();
			File myFilePath = new File(filePath);
			myFilePath.delete(); // 删除空文件夹
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * 
	 * @param path
	 * @return
	 */
	public static boolean delAllFile(String path)
	{
		boolean flag = false;
		File file = new File(path);
		if (!file.exists())
		{
			return flag;
		}
		if (!file.isDirectory())
		{
			return flag;
		}
		String[] tempList = file.list();
		File temp = null;
		for (int i = 0; i < tempList.length; i++)
		{
			if (path.endsWith(File.separator))
			{
				temp = new File(path + tempList[i]);
			}
			else
			{
				temp = new File(path + File.separator + tempList[i]);
			}
			if (temp.isFile())
			{
				temp.delete();
			}
			if (temp.isDirectory())
			{
				delAllFile(path + File.separator + tempList[i]);// 先删除文件夹里面的文件
				delFolder(path + File.separator + tempList[i]);// 再删除空文件夹
				flag = true;
			}
		}
		return flag;
	}

}
